package edu.ec.tesis.prototiporecomendador.ngc.UserProfile;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import com.hp.hpl.jena.ontology.OntModel;
import edu.ec.tesis.prototiporecomendador.mdl.Rating;
import edu.ec.tesis.prototiporecomendador.ngc.IMDBQuery.IMDBReader;
import edu.ec.tesis.prototiporecomendador.ngc.IMDBQuery.MovieIMDB;
import edu.ec.tesis.prototiporecomendador.ngc.Recomendadores.Semantico.RecomendadorSemantico;

import java.util.logging.Level;
import java.util.logging.Logger;

public class UserProfile {

    /**
     * Metodo encargado de crear los perfiles de usuario a partir de las bases
     * MovieLens
     */
    public static void cargarPerfilesUsuario(int numCalf) {
        //obtengo las configuraciones del sistema
        Configuration conf = Configuration.getInstance();

        //obtengo la lista de peliculas definidas en DBMOVIES (base de peliculas)
        ArrayList<String> movies = UserDataFileReader.readLines(conf.getDBMOVIES());

        //obtengo las calificaciones agrupadas por usuario de la DBRATINGS (base de ratings)
        ArrayList<ArrayList<Calificacion>> agrupados = UserDataFileReader.RatingsReadLines(conf.getDBRATINGS());
        Iterator<ArrayList<Calificacion>> ite = agrupados.iterator();
        //recorro los grupos, osea recorro los usuarios
        while (ite.hasNext()) {
            try {
                ArrayList<Calificacion> grupo = ite.next();
                /*ArrayList<Calificacion> grupo = new ArrayList<Calificacion>();
                 if (numCalf == 0) {
                 numCalf = grupo1.size();
                 }
                 for (int i = 0; i < numCalf; i++) {
                 if (grupo1.size() >= numCalf) {
                 grupo.add(grupo1.get(i));
                 }
                 }*/
                if (!grupo.isEmpty()) {
                    System.out.println("");
                    System.out.println("user " + grupo.get(0).getIdUser());

                    //obtengo el perfil-ontologia de usuario, si no existe se crea
                    OntModel user = UserOntologyManager.getUserModel(grupo.get(0).getIdUser(), conf);
                    int cont = 0;
                    Iterator<Calificacion> ite2 = grupo.iterator();
                    //recorro las calificaciones del usuario
                    while (ite2.hasNext()) {
                        cont++;
                        Calificacion cal = ite2.next();

                        System.out.print("|");

                        //compruebo que la pelicula sea de train o de test
                        boolean isTest = isTestMovie(cal, conf);
                        //boolean isTest = false;
                        //if (isTest || cont <= numCalf) {
                        //encuentro la pelicula en la lista
                        String movieLine = findMovieLine(cal.getIdMovie(), movies);

                        //cargo la MovieIMDB
                        MovieIMDB movieIMDb = IMDBReader.getMovieIMDB(movieLine, conf);

                        //cargo la pelicula en el modelo
                        if (movieIMDb != null) {
                            user = UserOntologyManager.fillOntology(user, movieIMDb, cal, conf, isTest);
                        }
                        //}
                    }

                    //propago los DOI en las caracteristicas semanticas de los contenidos formalizados en la ontologia
                    user = UserOntologyManager.doiPropagation(user, grupo.get(0).getIdUser(), conf, true);

                    //guardo el perfil-ontolog�a
                    try {
                        String path = conf.getONTOLOGYUSER() + grupo.get(0).getIdUser() + ".owl";
                        FileWriter f1 = new FileWriter(path);
                        BufferedWriter b1 = new BufferedWriter(f1);
                        user.write(b1, "RDF/XML");
                        b1.close();
                        user.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        System.out.println(e.getMessage());

                    }
                }
            } catch (NoExisteLaOntologiaException e) {
                // TODO Auto-generated catch block
                System.out.println("UserProfile.cargarPerfilesUsuario() Error: " + e.getMessage());
            } catch (NoSePudoPersistirElModeloException e) {
                // TODO Auto-generated catch block
                System.out.println("UserProfile.cargarPerfilesUsuario() Error: " + e.getMessage());
            }
        }
    }

    /**
     * Metodo encargado de crear las ontologias de peliculas de las bases
     * MovieLens
     *
     * @param usuario
     */
    public void crearPerfil(edu.ec.tesis.prototiporecomendador.mdl.User usuario) {
        Configuration conf = Configuration.getInstance();

        //obtengo la lista de peliculas definidas en DBMOVIES (base de peliculas)
        ArrayList<String> movies = UserDataFileReader.readLines(conf.getDBMOVIES());
        try {
            ArrayList<Rating> grupo = (ArrayList) usuario.getRatingList();

            if (!grupo.isEmpty()) {
                System.out.println("");
                System.out.println("user " + grupo.get(0).getUser().getIdUser());

                //obtengo el perfil-ontologia de usuario, si no existe se crea
                OntModel user = UserOntologyManager.getUserModel(grupo.get(0).getUser().getIdUser(), conf);
                int cont = 0;
                Iterator<Rating> ite2 = grupo.iterator();
                //recorro las calificaciones del usuario
                while (ite2.hasNext()) {
                    cont++;
                    Rating cal = ite2.next();
                    Calificacion calif = new Calificacion(cal.getUser().getIdUser(), cal.getRating(), cal.getMovies().getIdMovie());
                    System.out.print("|");

                    String movieLine = findMovieLine(cal.getMovies().getIdMovie(), movies);
                    //cargo la MovieIMDB
                    MovieIMDB movieIMDb = IMDBReader.getMovieIMDB(movieLine, conf);
                    //cargo la pelicula en el modelo
                    if (movieIMDb != null) {
                        user = UserOntologyManager.fillOntology(user, movieIMDb, calif, conf, false);
                    }
                    //}
                }

                //propago los DOI en las caracteristicas semanticas de los contenidos formalizados en la ontologia
                user = UserOntologyManager.doiPropagation(user, grupo.get(0).getUser().getIdUser(), conf, true);

                //guardo el perfil-ontolog�a
                try {
                    String path = conf.getONTOLOGYUSER() + grupo.get(0).getUser().getIdUser() + ".owl";
                    FileWriter f1 = new FileWriter(path);
                    BufferedWriter b1 = new BufferedWriter(f1);
                    user.write(b1, "RDF/XML");
                    b1.close();
                    user.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    System.out.println(e.getMessage());

                }
            }
        } catch (NoExisteLaOntologiaException e) {
            // TODO Auto-generated catch block
            System.out.println("UserProfile.cargarPerfilesUsuario() Error: " + e.getMessage());
        } catch (NoSePudoPersistirElModeloException e) {
            // TODO Auto-generated catch block
            System.out.println("UserProfile.cargarPerfilesUsuario() Error: " + e.getMessage());
        }
    }

    public static void cargarPelicula() {
        try {
            //obtengo las configuraciones del sistema
            Configuration conf = Configuration.getInstance();

            //obtengo la lista de peliculas definidas en DBMOVIES (base de peliculas)
            ArrayList<String> movies = UserDataFileReader.readLines(conf.getDBMOVIES());

            //obtengo el perfil-ontologia de pelicula, si no existe se crea
            OntModel movie = UserOntologyManager.getMovieModel(conf);
            int count = 0;
            while (movies.size() >= count) {
                count++;
                //encuentro la pelicula en la lista
                String movieLine = findMovieLine(count, movies);
                //cargo la MovieIMDB
                MovieIMDB movieIMDb = IMDBReader.getMovieIMDB(movieLine, conf);
                System.out.println("|" + count + "sss" + movieIMDb);

                //cargo la pelicula en el modelo
                if (movieIMDb != null) {
                    movie = UserOntologyManager.fillOntology(movie, movieIMDb, conf);
                }
                //guardo el perfil-ontolog�a
                String path = conf.getMOVIESIMDB();
                System.err.println(path);
                FileWriter f1;
                try {
                    f1 = new FileWriter(path);
                    BufferedWriter b1 = new BufferedWriter(f1);
                    movie.write(b1, "RDF/XML");
                    b1.close();

                } catch (IOException ex) {
                    Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
            movie.close(); //cerramos la ontologia
        } catch (NoSePudoPersistirElModeloException ex) {
            Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoExisteLaOntologiaException ex) {
            Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Retorna true en caso de que la pelicula calificada sea de test
     *
     * @param calification es la calificacion que un usuario da a una pelicula
     * @param conf es la configuracion del sistema
     * @return true si la pelicula es de test, false en caso contrario
     */
    private static boolean isTestMovie(Calificacion calificacion, Configuration conf) {

        //obtengo las peliculas test agrupadas por usuario de DBTEST (base de peliculas para test)
        ArrayList<ArrayList<Calificacion>> agrupados = UserDataFileReader.RatingsReadLines(conf.getDBTEST());
        Iterator<ArrayList<Calificacion>> ite = agrupados.iterator();
        //recorro los grupos, osea recorro los usuarios
        while (ite.hasNext()) {
            ArrayList<Calificacion> grupo = ite.next();
            if (!grupo.isEmpty()) {
                //obtengo el id del usuario puntero
                int iduser = grupo.get(0).getIdUser();
                /*si el usuario puntero coinside con el usuario buscado 
                 se comprueba si la pelicula calificada es de test*/
                if (iduser == calificacion.getIdUser()) {
                    Iterator<Calificacion> ite2 = grupo.iterator();
                    //recorro las calificaciones del usuario puntero
                    while (ite2.hasNext()) {
                        Calificacion cal = ite2.next();
                        //compruebo que la pelicula buscada este entre las peliculas test del usuario
                        if (cal.getIdMovie() == calificacion.getIdMovie()) {
                            return true;
                        }
                    }
                    //si no esta entre las peliculas test retorno false;
                    return false;
                }
            }
        }
        return false;
    }

    /**
     * Retorna la informacion del contenido identificado con
     * <code>idMovie</code> de la lista de contenidos <code>movies</code>
     *
     * @param idMovie identificador del contenido buscado
     * @param movies lista de los contenidos definidos en la base de datos de
     * MovieLens
     * @return informacion del contenido buscado
     */
    private static String findMovieLine(int idMovie, ArrayList<String> movies) {
        Iterator<String> iterator = movies.iterator();
        while (iterator.hasNext()) {
            String pivot = iterator.next();
            String campos[] = pivot.split("::");
            int idMoviePivot = Integer.parseInt(campos[0]);

            if (idMovie == idMoviePivot) {
                return pivot;
            }
        }
        return null;
    }

}
